home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / extensions / samples / videowarp.c < prev    next >
C/C++ Source or Header  |  1996-11-11  |  15KB  |  560 lines

  1. /*
  2.  * Copyright (c) 1994 Silicon Graphics, Inc.
  3.  * 
  4.  * Permission to use, copy, modify, distribute, and sell this software and
  5.  * its documentation for any purpose is hereby granted without fee,
  6.  * provided that (i) the above copyright notices and this permission
  7.  * notice appear in all copies of the software and related documentation,
  8.  * and (ii) the name of Silicon Graphics may not be used in any
  9.  * advertising or publicity relating to the software without the specific,
  10.  * prior written permission of Silicon Graphics.
  11.  * 
  12.  * THE SOFTWARE IS PROVIDED "AS-IS" AND WITHOUT WARRANTY OF ANY KIND,
  13.  * EXPRESS, IMPLIED OR OTHERWISE, INCLUDING WITHOUT LIMITATION, ANY
  14.  * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE.
  15.  * 
  16.  * IN NO EVENT SHALL SILICON GRAPHICS BE LIABLE FOR ANY SPECIAL,
  17.  * INCIDENTAL, INDIRECT OR CONSEQUENTIAL DAMAGES OF ANY KIND, OR ANY
  18.  * DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
  19.  * OR NOT ADVISED OF THE POSSIBILITY OF DAMAGE, AND ON ANY THEORY OF
  20.  * LIABILITY, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
  21.  * OF THIS SOFTWARE.
  22.  */
  23. /*
  24.  * videowarp.c
  25.  *
  26.  * Demonstrate video-to-texture transfers from Sirius in OpenGL.
  27.  *
  28.  * The video image is warpped as if it is on a rubber sheet whose sides are
  29.  * pinned down but the center is being twisted back a forth.
  30.  *
  31.  * See the usage() function for the command line options (or run with -h).
  32.  *
  33.  * Keys: w - toggle warping on/off
  34.  *
  35.  * Algorithm:
  36.  *  The video frames are copied to texture memory
  37.  *  The texture is mapped onto a spline mesh that for which the control point
  38.  *  are rotated back and forth thus resulting in a warping effect.
  39.  *
  40.  * $Revision: 1.1 $
  41.  */
  42.  
  43. #include <stdlib.h>
  44. #include <stdio.h>
  45. #include <getopt.h>
  46. #include <X11/keysym.h>
  47. #include <device.h>
  48. #include <vl/vl.h>
  49. #include <vl/dev_sirius.h>
  50. #include <GL/glx.h>
  51. #include <GL/glu.h>
  52. #include "xwindow.h"
  53.  
  54. GLenum  internalTextureFormat;
  55.  
  56. static float texture_matrix[4][4] = {
  57.     1, 0, 0, 0,
  58.     0, 1, 0, 0,
  59.     0, 0, 1, 0,
  60.     0, 0, 0, 1
  61.  
  62. };
  63.  
  64. /*
  65.  * VL defines
  66.  */
  67. VLControlValue    size, timing;
  68. VLControlValue     format;
  69. VLControlValue     cap_type;
  70. VLServer    svr;
  71. VLPath        path;
  72. VLNode        src;
  73. VLNode        drn;
  74.  
  75. /* OpenGL/X variables */
  76. Display *dpy;
  77. Window window;
  78. #ifdef GLX_SGIX_video_source
  79. GLXVideoSourceSGIX glxVideoSource;
  80. #else  /* Make the compiler barf */
  81. GLX_SGIX_video_source is not defined in this version of the library
  82. #endif
  83.  
  84. /* parameters of the evaluator map for vertexes */
  85. #define S_ORDER 4
  86. #define T_ORDER 4
  87. #define S_SEGMENTS 10
  88. #define T_SEGMENTS 10
  89. #define S_MAPS 2
  90. #define T_MAPS 2
  91.  
  92. #define DELTA_ROT 10
  93. float rotang = DELTA_ROT;
  94. float totang = 0;
  95. int s_points, t_points;
  96. int s_stride, t_stride;
  97.  
  98. /*
  99.  * function prototypes
  100.  */
  101. void usage(char *, int);
  102. void initVideo(int, int, int);
  103. void initGfx(int argc, char *argv[],  int packingFormat);
  104. void initWarp(void);
  105. void initVertCoords(void);
  106. void cleanup(void);
  107. void displayFrame(void);
  108. void processEvents(void);
  109. void updateVideoFormat(void);
  110.  
  111. int
  112. main(int argc, char **argv)
  113. {
  114.  
  115.     int        c, insrc = VL_ANY;
  116.     int     device = VL_ANY;
  117.     short    dev, val;
  118.     int        packingFormat = 5;
  119.  
  120.     /* Parse the input string */
  121.     while ((c = getopt(argc, argv, "n:t:v:hwFgpm")) != EOF ) {
  122.         switch (c) {
  123.       case 'n':
  124.         device = atoi(optarg); /* user can override default device */
  125.         break;
  126.       case 't':
  127.         packingFormat = atoi(optarg);
  128.         break;
  129.       case 'v':
  130.         insrc = atoi(optarg);
  131.         break;
  132.       case 'h':
  133.         usage(argv[0], EXIT_SUCCESS);
  134.       default:
  135.         usage(argv[0], EXIT_FAILURE);
  136.         }
  137.     }
  138.  
  139.     initVideo(insrc, device, packingFormat);
  140.  
  141.     updateVideoFormat();
  142.     
  143.     initGfx(argc, argv, packingFormat);
  144.     
  145.     vlBeginTransfer(svr, path, 0, NULL);
  146.  
  147.     while (TRUE) {
  148.     if (XEventsQueued(dpy, QueuedAfterReading)) {
  149.         XEvent event;
  150.  
  151.         XNextEvent(dpy, &event);
  152.         switch (event.type) {
  153.           case KeyPress: {
  154.                   KeySym key;
  155.                   (void) XLookupString(&event.xkey, NULL, 0, &key, NULL);
  156.                   switch (key) {
  157.                     case XK_Escape:
  158.                       exit(EXIT_FAILURE);
  159.                       break;
  160.                     case XK_w:
  161.               rotang = rotang == 0 ? DELTA_ROT : 0;
  162.               break;
  163.             case XK_i:
  164.               totang = 0;
  165.               initVertCoords();
  166.               break;
  167.                     case XK_h:
  168.                     case XK_H:
  169.                     case XK_question:
  170.                       printf("Keys:\tw - toggle warpping on/off\n");
  171.                       printf("\th/? - help\n");
  172.                       printf("\tEsc - quit\n");
  173.                       break;
  174.                   }
  175.               }
  176.         }
  177.     }
  178.  
  179.     /* Check for VL events if any ... */
  180.     processEvents();
  181.     /* Next frame of data */
  182.     displayFrame();
  183.     glXSwapBuffers(dpy, window);
  184.     }
  185. }
  186.  
  187.  
  188. void
  189. initVideo(int insrc, int device, int packingFormat)
  190. {
  191.     VLControlValue texctl;
  192.  
  193.     /* open the server */
  194.     if (!(svr = vlOpenVideo(""))) {
  195.     printf("couldn't open video\n");
  196.     exit(EXIT_FAILURE);
  197.     }
  198.  
  199.     /* Get the Video source */
  200.     src = vlGetNode(svr, VL_SRC, VL_VIDEO, insrc);
  201.     /* Get the Texture drain */
  202.     drn = vlGetNode(svr, VL_DRN, VL_TEXTURE, 0);
  203.  
  204.     /* Create path   */
  205.     path = vlCreatePath(svr, device, src, drn);
  206.     if (path < 0) {
  207.     vlPerror("vlCreatePath");
  208.     exit(EXIT_FAILURE);
  209.     }
  210.  
  211.     /* setup path */
  212.     if (vlSetupPaths(svr, (VLPathList)&path, 1, VL_SHARE, VL_SHARE) < 0) {
  213.     vlPerror("vlSetupPaths");
  214.     exit(EXIT_FAILURE);
  215.     }
  216.     /* select the appropriate events */
  217.     if (vlSelectEvents(svr, path, VLStreamPreemptedMask |
  218.                             VLControlChangedMask ) < 0) {
  219.             vlPerror("Select Events");
  220.             exit(EXIT_FAILURE);
  221.     }
  222.     cap_type.intVal = VL_CAPTURE_INTERLEAVED;
  223.     
  224.     if (vlSetControl(svr, path, drn, VL_CAP_TYPE, &cap_type) <0) {
  225.     vlPerror("VlSetControl");
  226.     exit(EXIT_FAILURE);
  227.     }
  228.  
  229.     switch(packingFormat) {
  230.       case 4:
  231.     texctl.intVal = SIR_TEX_PACK_RGBA_4;
  232.     break;
  233.       case 8:
  234.     texctl.intVal = SIR_TEX_PACK_RGBA_8;
  235.     break;
  236.       case 5:
  237.       default:
  238.     texctl.intVal = SIR_TEX_PACK_RGB_5;
  239.     break;
  240.     }
  241.  
  242.     /* Set the Texture packing mode */
  243.     if (vlSetControl(svr, path, drn, VL_PACKING, &texctl) <0) {
  244.         vlPerror("VlSetControl");
  245.         exit(EXIT_FAILURE);
  246.     }
  247.     updateVideoFormat();
  248. }
  249.  
  250. void
  251. usage(char *name, int exitStatus)
  252. {
  253.     fprintf(stderr, "usage: %s [-n#] [-v#] [-t#] [-h (for help)]\n", name);
  254.     fprintf(stderr, "\t-n#  video device number (as reported by vlinfo)\n");
  255.     fprintf(stderr, "\t-v#  video input number (as reported by vlinfo)\n");
  256.     fprintf(stderr, "\t-t#  texture format (as packed by Sirius)\n");
  257.     fprintf(stderr,
  258.             "\tInteractively, `h/?' keys provide description of interface\n");
  259.     exit(exitStatus);
  260. }
  261.  
  262. /*
  263.  * CreateTexture: Create a texture map with correct attributes.
  264.  */
  265. int t_width, t_height;
  266.  
  267. void
  268. initGfx(int argc, char *argv[],  int packingFormat)
  269. {
  270.     GLubyte fakeTexture[1024][1024][3];
  271.     float s_scale, t_scale;
  272.  
  273.     GLXContext ctx;
  274.     int visualAttr[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_RED_SIZE, 1,
  275.                         GLX_DEPTH_SIZE, 0, GLX_STENCIL_SIZE, 0,
  276.                         None};
  277.  
  278.     createWindowAndContext(&dpy, &window, &ctx,
  279.                            100, 100, 100 + size.xyVal.x, 100 + size.xyVal.y,
  280.                            GL_FALSE, NULL, visualAttr, argv[0]);
  281.  
  282.     glxVideoSource = glXCreateGLXVideoSourceSGIX(dpy, DefaultScreen(dpy), svr,
  283.                                                  path, VL_TEXTURE, drn);
  284.     if (glxVideoSource == None) {
  285.         fprintf(stderr, "can't create video source\n");
  286.         exit(EXIT_FAILURE);
  287.     }
  288.     if (!glXMakeCurrentReadSGI(dpy, window, glxVideoSource, ctx)) {
  289.         fprintf(stderr, "Can't make current to video\n");
  290.         exit(EXIT_FAILURE);
  291.     }
  292.  
  293.     /*
  294.      * Set up texture parameters.
  295.      */
  296.     /* Match internal format to external packing format */
  297.     switch(packingFormat) {
  298.       case 4:
  299.     internalTextureFormat = GL_RGBA4_EXT;
  300.     printf ("using RGBA4\n");
  301.     break;
  302.       case 8:
  303.     internalTextureFormat = GL_RGBA8_EXT;
  304.     printf ("using RGBA8\n");
  305.     break;
  306.       case 5:
  307.       default:
  308.     internalTextureFormat = GL_RGB5_EXT;
  309.     printf ("using RGB5\n");
  310.     break;
  311.     }
  312.  
  313.     /*
  314.      * 625 textures are bigger than 525 textures
  315.      */
  316.     if ((timing.intVal == VL_TIMING_525_SQ_PIX) ||
  317.         (timing.intVal == VL_TIMING_525_CCIR601)) {
  318.     t_width = 1024;
  319.     t_height = 512;
  320.     } else {
  321.     t_width = 1024;
  322.     t_height = 1024;
  323.     }
  324.  
  325.     s_scale = (size.xyVal.x - 1) / (float)t_width;
  326.     t_scale = size.xyVal.y / (float)t_height;
  327.     texture_matrix[0][0] =  s_scale;
  328.     texture_matrix[1][1] = -t_scale;
  329.     texture_matrix[3][1] =  t_scale;
  330.  
  331.     initWarp();
  332.     glEnable(GL_TEXTURE_2D);
  333.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
  334.     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
  335.     glTexImage2D(GL_TEXTURE_2D, 0, internalTextureFormat, t_width, t_height,
  336.                  0, GL_RGB, GL_UNSIGNED_BYTE, fakeTexture);
  337.  
  338.     glMatrixMode(GL_TEXTURE);
  339.     glLoadMatrixf((GLfloat *) texture_matrix);
  340.  
  341.     glMatrixMode(GL_PROJECTION);
  342.     glLoadIdentity();
  343.     gluPerspective(60, 1, 1, 10);
  344.     glMatrixMode(GL_MODELVIEW);
  345.     glLoadIdentity();
  346.     glTranslatef(0., 0., - 7);
  347.     glTranslatef(-(s_points - 1)/2.0, -(t_points - 1)/2.0, 0);
  348.     /* Setup tranfromation matrices */
  349.     glMapGrid2f(S_SEGMENTS, 0, 1, T_SEGMENTS, 0, 1);
  350.  
  351.     glEnable(GL_MAP2_TEXTURE_COORD_2);
  352.     glEnable(GL_MAP2_VERTEX_3);
  353. }
  354.  
  355. void
  356. cleanup()
  357. {
  358.     vlEndTransfer(svr, path);
  359.     vlDestroyPath(svr, path);
  360.     vlCloseVideo(svr);
  361.     exit(EXIT_SUCCESS);
  362. }
  363.  
  364. void
  365. processEvents()
  366. {
  367.     VLEvent ev;
  368.  
  369.     /* Check to see if any controls changed or if the video
  370.      * path has been pre-empted.
  371.      */
  372.     if (vlCheckEvent(svr, VLControlChangedMask|
  373.                      VLStreamPreemptedMask, &ev) == -1) {
  374.     return;
  375.     }
  376.     switch(ev.reason) {
  377.       case VLStreamPreempted:
  378.         cleanup();
  379.     break;
  380.       case VLControlChanged:
  381.         switch(ev.vlcontrolchanged.type) {
  382.           case VL_TIMING:
  383.           case VL_SIZE:
  384.           case VL_PACKING:
  385.             updateVideoFormat();
  386.             printf("got timing, size, or packing event\n");
  387.             break;
  388.           default:
  389.             break;
  390.         }
  391.             break;
  392.       default:
  393.     break;
  394.     }
  395. }
  396.  
  397. void
  398. updateVideoFormat()
  399. {
  400.     /* Get the timing from input source */
  401.     if (vlGetControl(svr, path, src, VL_TIMING, &timing) < 0) {
  402.     vlPerror("vlGetControl");
  403.     exit(EXIT_FAILURE);
  404.     }
  405.  
  406.     /* Set texture drain's timing to input source */
  407.     if (vlSetControl(svr, path, drn, VL_TIMING, &timing) < 0) {
  408.     vlPerror("vlSetControl");
  409.     exit(EXIT_FAILURE);
  410.     }
  411.  
  412.     if (vlGetControl(svr, path, src, VL_SIZE, &size) < 0) {
  413.     vlPerror("vlSetupPaths");
  414.     exit(EXIT_FAILURE);
  415.     }
  416.     printf("control size: %3d x %3d\n", size.xyVal.x, size.xyVal.y);
  417. }
  418.  
  419. /**************************************************************************/
  420.  
  421. /*
  422.  * Routines to warp the video.
  423.  */
  424. /* parameters of the evaluator map for texture coords */
  425. int tx_s_stride, tx_t_stride;
  426. int tx_s_points, tx_t_points;
  427. int tx_ncomp = 2;
  428.  
  429. float limitang = 220;
  430.  
  431. GLfloat *textureMap = NULL, *vertexMap = NULL;
  432.  
  433. /*
  434.  * Initialize the evaluators used for the warping.
  435.  */
  436. void
  437. initWarp(void)
  438. {
  439.     int s, t;
  440.     GLfloat *p;
  441.  
  442.     /* the vertex coord map starts out regularly spaced; it's warped later */
  443.        
  444.     s_points = S_ORDER + (S_MAPS - 1) * (S_ORDER - 1);
  445.     t_points = T_ORDER + (T_MAPS - 1) * (T_ORDER - 1);
  446.     s_stride = 3;
  447.     t_stride = 3 * s_points;
  448.     /* the texture coord map is just a linear, regularly spaced grid */
  449.     
  450.     tx_s_points = S_MAPS + 1;
  451.     tx_t_points = T_MAPS + 1;
  452.     tx_s_stride = tx_ncomp;
  453.     tx_t_stride = tx_ncomp * tx_s_points;
  454.     textureMap = malloc(tx_s_points * tx_t_points * tx_ncomp * sizeof(GLfloat));
  455.       vertexMap = malloc(s_points * t_points * 3 * sizeof(GLfloat));
  456.  
  457.     initVertCoords();
  458.     p = textureMap;
  459.     for (t = 0; t < tx_t_points; t++) {
  460.     for (s = 0; s < tx_s_points; s++, p += tx_ncomp) {
  461.         p[0] = s/(tx_s_points - 1.0);
  462.         p[1] = t/(tx_t_points - 1.0);
  463.     }
  464.     }
  465. }
  466.  
  467. void
  468. initVertCoords()
  469. {
  470.     GLfloat *p;
  471.     int s, t;
  472.  
  473.     p = vertexMap;
  474.     for (t = 0; t < t_points; t++) {
  475.     for (s = 0; s < s_points; s++, p += 3) {
  476.         p[0] = s;
  477.         p[1] = t;
  478.         p[2] = 0;
  479.     }
  480.     }
  481. }
  482.  
  483. void
  484. rotate_pts(int level, float ang)
  485. {
  486.     int i, s, t;
  487.     float *p, v[3], tv[3];
  488.     float x, y, z;
  489.     float ts, tt;
  490.     GLfloat mat[4][4];
  491.  
  492.     /* use the GL to compute our rotation matrix, then read it back */
  493.     /* not recommended for programs that care about performance :-) */
  494.     glPushMatrix();
  495.     glLoadIdentity();
  496.     glTranslatef((s_points - 1)/2.0, (t_points - 1)/2.0, 0);
  497.     glRotatef(ang, 0, 0, 1);
  498.     glTranslatef(-(s_points - 1)/2.0, -(t_points - 1)/2.0, 0);
  499.     glGetFloatv(GL_MODELVIEW_MATRIX, &mat[0][0]);
  500.     glPopMatrix();
  501.  
  502.     for (t = level; t < t_points - level; t++) {
  503.     for (s = level; s < s_points - level; s++) {
  504.         if (s > level && s < s_points - level - 1 &&
  505.                 t > level && t < t_points - level - 1){
  506.         continue;
  507.         }
  508.         p = vertexMap + t * t_stride + s * s_stride;
  509.             /* Transform the control point */
  510.             tv[0] = p[0] * mat[0][0] + p[1] * mat[1][0] + p[2] * mat[2][0] +
  511.                 mat[3][0];
  512.             tv[1] = p[0] * mat[0][1] + p[1] * mat[1][1] + p[2] * mat[2][1] +
  513.                 mat[3][1];
  514.             tv[2] = p[0] * mat[0][2] + p[1] * mat[1][2] + p[2] * mat[2][2] +
  515.                 mat[3][2];
  516.  
  517.         p[0] = tv[0];
  518.         p[1] = tv[1];
  519.         p[2] = tv[2];
  520.     }
  521.     }
  522.     totang += rotang;
  523.     if (limitang != 0 && (totang > limitang || totang < -limitang)) {
  524.     rotang = -rotang;
  525.     }
  526. }
  527.  
  528. /*
  529.  * displayFrame: Display a new texture. This routine is called at 30
  530.  * Hz for 525 timing and 25Hz for 625 timing.
  531.  */
  532. void
  533. displayFrame()
  534. {
  535.     int is, it;
  536.     float *p;
  537.  
  538.     /* Load the texture from Sirius to Texture memory */
  539.     glCopyTexSubImage2DEXT(GL_TEXTURE_2D, 0, 0, 0, 0, 0, 768, t_height);
  540.  
  541.     glClear(GL_COLOR_BUFFER_BIT);
  542.     glEnable(GL_TEXTURE_2D);
  543.     rotate_pts(1, rotang);
  544.     rotate_pts(2, 0.5 * rotang);
  545.  
  546.     for (it = 0; it < T_MAPS; it++) {
  547.     for (is = 0; is < S_MAPS; is++) {
  548.         p = vertexMap + it * t_stride * (T_ORDER - 1) +
  549.         is * s_stride * (S_ORDER - 1);
  550.         glMap2f(GL_MAP2_VERTEX_3, 0, 1,
  551.             s_stride, 4, 0, 1, t_stride, 4, p);
  552.         p = textureMap + it * tx_t_stride + is * tx_s_stride;
  553.         glMap2f(GL_MAP2_TEXTURE_COORD_2, 0, 1,
  554.             tx_s_stride, 2, 0, 1, tx_t_stride, 2, p);
  555.         glEvalMesh2(GL_FILL, 0, S_SEGMENTS, 0, T_SEGMENTS);
  556.     }
  557.     }
  558.     glDisable(GL_TEXTURE_2D);
  559. }
  560.